package com.cisco.vsx.email.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringWriter;

import javax.mail.internet.MimeMessage;

import org.apache.log4j.Logger;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Component;

import com.cisco.vsx.email.IEmailSender;
import com.cisco.vsx.email.TemplateContent;
import com.cisco.vsx.email.VSXMailMessage;
import com.cisco.vsx.email.service.IEmailTemplateService;

/**
 * @author naresred
 * 
 */

@Component
public class EmailSenderImpl implements IEmailSender {

	private final VelocityEngine velocityEngine;
	private final JavaMailSender mailSender;
	
	private static Logger logger = Logger.getLogger(EmailSenderImpl.class);

	@Autowired
	public EmailSenderImpl(VelocityEngine velocityEngine, JavaMailSender mailSender) {
		this.velocityEngine = velocityEngine;
		this.mailSender = mailSender;
	}
	
	@Autowired
	private IEmailTemplateService emailTemplateService;

	@Override
	public void send(final VSXMailMessage msg) {
		logger.debug("Entered [send] of [EmailSenderImpl]");
		MimeMessagePreparator preparator = new MimeMessagePreparator() {
			public void prepare(MimeMessage mimeMessage) throws Exception {
				MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true);
				message.setTo(msg.getTo());
				message.setFrom(msg.getFrom());
				
				VelocityContext subjectContext = new VelocityContext(msg.getSubjectModel());
				StringWriter subjectWriter = new StringWriter();
				Reader subjectReader = emailTemplateService.getTemplateContentReader(msg.getSubjectTemplateId());
				velocityEngine.evaluate(subjectContext, subjectWriter, "vsx", subjectReader);
				message.setSubject(subjectWriter.toString());
				
				StringBuilder bodyBuilder = new StringBuilder();
				
				if (msg.isIncludeHeader()) {
					VelocityContext headerContext = new VelocityContext();
					StringWriter headerWriter = new StringWriter();
					Reader headerReader = emailTemplateService.getTemplateContentReader(msg.getHeaderTemplateId());
					velocityEngine.evaluate(headerContext, headerWriter, "vsx", headerReader);
					
					bodyBuilder.append(headerWriter.toString());			
				}
				
				VelocityContext bodyContext = new VelocityContext(msg.getSubjectModel());
				StringWriter bodyWriter = new StringWriter();
				Reader bodyReader = emailTemplateService.getTemplateContentReader(msg.getBodyTemplateId());
				velocityEngine.evaluate(bodyContext, bodyWriter, "vsx", bodyReader);
				
				bodyBuilder.append(bodyWriter.toString());
				
				if (msg.isIncludeFooter()) {
					VelocityContext footerContext = new VelocityContext();
					StringWriter footerWriter = new StringWriter();
					Reader footerReader = emailTemplateService.getTemplateContentReader(msg.getFooterTemplateId());
					velocityEngine.evaluate(footerContext, footerWriter, "vsx", footerReader);
					
					bodyBuilder.append(footerWriter.toString());
				}
				
				message.setText(bodyBuilder.toString(), true);
				
				// Add Images
				
				for (TemplateContent imageContent : msg.getImages()) {
					InputStreamSource iss = new ByteArrayResource(getBytes(imageContent.getContent()));
					message.addInline(imageContent.getName(), iss, imageContent.getMimeType());					
//					message.addAttachment(key.toString().trim()+".jpg", iss);
				}
				
				// Add Attachments
				
				for (TemplateContent attachmentContent : msg.getAttachments()) {
					InputStreamSource iss = new ByteArrayResource(getBytes(attachmentContent.getContent()));
					message.addInline(attachmentContent.getName(), iss, attachmentContent.getMimeType());					
					message.addAttachment(attachmentContent.getName()+".txt", iss);
				}
			}
		};

		mailSender.send(preparator);
	}	
	
	private static byte[] getBytes(InputStream is) throws IOException {
	    int len;
	    int size = 1024;
	    byte[] buf;

	    if (is instanceof ByteArrayInputStream) {
	      size = is.available();
	      buf = new byte[size];
	      len = is.read(buf, 0, size);
	    } else {
	      ByteArrayOutputStream bos = new ByteArrayOutputStream();
	      buf = new byte[size];
	      while ((len = is.read(buf, 0, size)) != -1)
	        bos.write(buf, 0, len);
	      buf = bos.toByteArray();
	    }
	    return buf;
	}
}
